﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YArchitech.Controls;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKStairs.CommonUnit;
using YJKStairs.DataInfos;

namespace YJKStairs.Manage
{
	public class StairsBeamCreator
	{
		public static bool CreateStairsBeam(Autodesk.Revit.DB.Document doc, string revitVersion, BeamInfo beamInfo, List<CurveInfo> beamPathCurveInfos, XYZ move)
		{
			if ((!beamInfo.BottomBeam && !beamInfo.TopBeam && !beamInfo.MiddleBeam) || beamPathCurveInfos.Count == 0)
			{
				return true;
			}
			string familyName = "混凝土-矩形梁";
			FamilySymbol familySymbol = StairsBeamCreator.GetFamilySymbol(doc, familyName, beamInfo.BeamWidth, beamInfo.BeamHeight, revitVersion);
			if (familySymbol == null)
			{
				return false;
			}
			if (beamInfo.BottomBeam)
			{
				CurveInfo curveInfo = beamPathCurveInfos[0];
				XYZ hyendPoint = curveInfo.CurveObj.GetEndPoint(0);
				XYZ hyendPoint2 = curveInfo.CurveObj.GetEndPoint(1);
				FamilyInstance familyInstance = StairsBeamCreator.CreateOneBeam(doc, familySymbol, hyendPoint, hyendPoint2, beamInfo.BottomElevation);
				ElementTransformUtils.MoveElement(doc, familyInstance.Id, new XYZ(move.X, move.Y, 0.0));
			}
			if (beamInfo.TopBeam)
			{
				CurveInfo curveInfo2 = beamPathCurveInfos[1];
				XYZ hyendPoint3 = curveInfo2.CurveObj.GetEndPoint(0);
				XYZ hyendPoint4 = curveInfo2.CurveObj.GetEndPoint(1);
				FamilyInstance familyInstance2 = StairsBeamCreator.CreateOneBeam(doc, familySymbol, hyendPoint3, hyendPoint4, beamInfo.TopElevation);
				ElementTransformUtils.MoveElement(doc, familyInstance2.Id, new XYZ(move.X, move.Y, 0.0));
			}
			if (beamInfo.MiddleBeam)
			{
				CurveInfo curveInfo3 = beamPathCurveInfos[2];
				XYZ hyendPoint5 = curveInfo3.CurveObj.GetEndPoint(0);
				XYZ hyendPoint6 = curveInfo3.CurveObj.GetEndPoint(1);
				FamilyInstance familyInstance3 = StairsBeamCreator.CreateOneBeam(doc, familySymbol, hyendPoint5, hyendPoint6, beamInfo.MiddleElevation);
				ElementTransformUtils.MoveElement(doc, familyInstance3.Id, new XYZ(move.X, move.Y, 0.0));
			}
			return true;
		}

		public static bool CreateStairsBeam(Autodesk.Revit.DB.Document doc, string revitVersion, BaseBeamData beamInfo, List<BeamCurveInfo> beamPathCurveInfos, XYZ move, Stairs stairs, XYZ ptInsert)
		{
			ElementSet elementSet = new ElementSet();
			if (beamPathCurveInfos.Count == 0)
			{
				return false;
			}
			string familyName = "混凝土-矩形梁";
			FamilySymbol familySymbol = StairsBeamCreator.GetFamilySymbol(doc, familyName, beamInfo.BeamWidth, beamInfo.BeamHeight, revitVersion);
			if (familySymbol == null)
			{
				return false;
			}
			List<ElementId> list = new List<ElementId>();
			foreach (BeamCurveInfo beamCurveInfo in beamPathCurveInfos)
			{
				if (beamCurveInfo.m_arCurveInfo.Count > 0)
				{
					foreach (CurveInfo curveInfo in beamCurveInfo.m_arCurveInfo)
					{
						if (!(null == curveInfo.CurveObj))
						{
							XYZ hyendPoint = curveInfo.CurveObj.GetEndPoint(0);
							XYZ hyendPoint2 = curveInfo.CurveObj.GetEndPoint(1);
							FamilyInstance familyInstance = StairsBeamCreator.CreateOneBeam(doc, familySymbol, hyendPoint, hyendPoint2, beamCurveInfo.m_BottomElevation);
							elementSet.Insert(familyInstance);
							ElementTransformUtils.MoveElement(doc, familyInstance.Id, new XYZ(move.X, move.Y, 0.0));
							if (ptInsert != null)
							{
								double viewRotateAngle = ViewUtils.GetViewRotateAngle(doc.ActiveView);
								Geometry.TransformElemnetAtPoint(doc, ptInsert, familyInstance.Id, viewRotateAngle);
							}
							ElementId materialIdByName = Common.GetMaterialIdByName(doc, "钢筋混凝土");
							Parameter parameter = familyInstance.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM);
							if (parameter != null && !parameter.IsReadOnly && materialIdByName != null)
							{
								parameter.Set(materialIdByName);
							}
							list.Add(familyInstance.Id);
						}
					}
				}
			}
			if (list.Count > 0)
			{
				string sStairsBeam = ElementXDataManager.m_sStairsBeam;
				ElementXDataManager.WriteStairsBeamXData(stairs, sStairsBeam, list);
			}
			try
			{
				elementSet.Insert(stairs);
				GroupType groupType = doc.CreatYJKGroup(elementSet).GroupType;
				if (groupType.CanBeRenamed && stairs.GetTypeId() != null)
				{
					StairsType stairsType = doc.GetElement(stairs.GetTypeId()) as StairsType;
					if (stairsType != null)
					{
						groupType.Name = stairsType.Name;
					}
				}
			}
			catch (Exception)
			{
				YJKMessageBox.Show("楼梯梯梁编辑组失败！");
				return true;
			}
			return true;
		}

		public static bool CreateStairsBeam(Autodesk.Revit.DB.Document doc, SteelStairs param_stairs, XYZ ptTopStart, XYZ ptTopEnd, XYZ ptBottomStart, XYZ ptBottomEnd)
		{
			XYZ ptInsert = param_stairs.m_ptInsert;
			SteelStairsBeamData beamData = param_stairs.m_BeamData;
			bool bTopBeam = beamData.m_bTopBeam;
			bool bBottomBeam = beamData.m_bBottomBeam;
			double dElevation = beamData.m_dElevation;
			double elevation = beamData.m_dElevation + param_stairs.m_dStairsHeight;
			FamilySymbol beamType = param_stairs.m_BeamType;
			if (beamType == null)
			{
				return false;
			}
			if (bBottomBeam)
			{
				FamilyInstance familyInstance = StairsBeamCreator.CreateOneBeam(doc, beamType, ptBottomEnd, ptBottomStart, dElevation);
				familyInstance.GetParameter("Z 轴偏移值").Set(-beamData.m_dBottomOffsetV);
				ElementTransformUtils.RotateElement(doc, familyInstance.Id, Line.CreateBound(ptInsert, new XYZ(ptInsert.X, ptInsert.Y, ptInsert.Z + 10.0)), param_stairs.m_dRotateAngle);
			}
			if (bTopBeam)
			{
				FamilyInstance familyInstance2 = StairsBeamCreator.CreateOneBeam(doc, beamType, ptTopEnd, ptTopStart, elevation);
				familyInstance2.GetParameter("Z 轴偏移值").Set(-beamData.m_dTopOffsetV);
				familyInstance2.GetParameter("Y 轴偏移值").Set(-beamData.m_dTopOffsetH);
				ElementTransformUtils.RotateElement(doc, familyInstance2.Id, Line.CreateBound(ptInsert, new XYZ(ptInsert.X, ptInsert.Y, ptInsert.Z + 10.0)), param_stairs.m_dRotateAngle);
			}
			return true;
		}

		private static FamilyInstance CreateOneBeam(Autodesk.Revit.DB.Document doc, FamilySymbol beamType, XYZ ptStart, XYZ ptEnd, double elevation)
		{
			double num = 0.0;
			ElementId elementId = null;
			Level level = StairsBeamCreator.GetLevel(doc, elevation, ref num, ref elementId);
			XYZ startPoint = new XYZ(ptStart.X, ptStart.Y, level.Elevation);
			XYZ endPoint = new XYZ(ptEnd.X, ptEnd.Y, level.Elevation);
			Line line = YJKLineEx.YJKGetBound(startPoint, endPoint);
			FamilyInstance familyInstance = null;
			try
			{
				UnifiedModified.ActivateFamilySymbol(beamType);
				familyInstance = doc.Create.NewFamilyInstance(line, beamType, level, (Autodesk.Revit.DB.Structure.StructuralType)1);
				if (!Geometry.IsEqual(num, 0.0))
				{
					familyInstance.get_Parameter(BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION).Set(num);
					familyInstance.get_Parameter(BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION).Set(num);
				}
				if (elementId != null)
				{
					StairsBeamCreator.DelLevel(doc, elementId);
				}
			}
			catch (Exception)
			{
				return null;
			}
			return familyInstance;
		}

		private static FamilySymbol GetFamilySymbol(Autodesk.Revit.DB.Document doc, string familyName, double width, double height, string revitVersion)
		{
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Family)).ToElements())
			{
				Family family = element as Family;
				if (family != null && familyName.ToUpper().CompareTo(family.Name.ToUpper()) == 0)
				{
					double num = Common.FeetToMM(width);
					double num2 = Common.FeetToMM(height);
					string text = num.ToString("f0") + "x" + num2.ToString("f0") + "mm";
					FamilySymbol familySymbol = null;
					foreach (FamilySymbol familySymbol2 in family.GetSymbols())
					{
						if (familySymbol == null)
						{
							familySymbol = familySymbol2;
						}
						if (text.ToUpper().CompareTo(familySymbol2.Name.ToUpper()) == 0)
						{
							return familySymbol2;
						}
					}
					FamilySymbol familySymbol3 = familySymbol.Duplicate(text) as FamilySymbol;
					familySymbol3.GetParameter("b").Set(width);
					familySymbol3.GetParameter("h").Set(height);
					return familySymbol3;
				}
			}
			string text2 = StairsBeamCreator.GetAppRootPath();
			text2 = text2 + "\\Templates\\" + revitVersion + "\\混凝土-矩形梁.rfa";
			if (!File.Exists(text2))
			{
				throw new Exception("Unsupported version");
			}
			doc.LoadFamily(text2);
			return StairsBeamCreator.GetFamilySymbol(doc, familyName, width, height, revitVersion);
		}

		private static string GetAppRootPath()
		{
			string location = Assembly.GetExecutingAssembly().Location;
			int length = location.LastIndexOf("\\");
			string text = location.Substring(0, length);
			length = text.LastIndexOf("\\");
			return text.Substring(0, length);
		}

		private static Level GetLevel(Autodesk.Revit.DB.Document doc, double elevation, ref double offset, ref ElementId newLevelId)
		{
			List<Level> sortLevels = Common.GetSortLevels(doc, double.MinValue, double.MaxValue);
			double num = double.MaxValue;
			int i = 0;
			int num2 = -1;
			while (i < sortLevels.Count)
			{
				Level level = sortLevels[i];
				if (!Geometry.GreaterThan(level.Elevation, elevation))
				{
					double num3 = elevation - level.Elevation;
					if (Geometry.LessThan(num3, num))
					{
						num2 = i;
						num = num3;
					}
				}
				i++;
			}
			Level level2;
			if (num2 != -1)
			{
				level2 = sortLevels[num2];
				offset = num;
			}
			else
			{
				level2 = StairsBeamCreator.NewLevel(doc, elevation);
				offset = 0.0;
				if (level2 != null)
				{
					newLevelId = level2.Id;
				}
			}
			return level2;
		}

		private static void DelLevel(Autodesk.Revit.DB.Document doc, ElementId LevelId)
		{
			if (LevelId != null)
			{
				doc.Delete(LevelId);
			}
		}

		private static Level GetLevel(Autodesk.Revit.DB.Document doc, double elevation, ref double offset)
		{
			List<Level> sortLevels = Common.GetSortLevels(doc, double.MinValue, double.MaxValue);
			double num = double.MaxValue;
			int i = 0;
			int num2 = -1;
			while (i < sortLevels.Count)
			{
				Level level = sortLevels[i];
				if (!Geometry.GreaterThan(level.Elevation, elevation))
				{
					double num3 = elevation - level.Elevation;
					if (Geometry.LessThan(num3, num))
					{
						num2 = i;
						num = num3;
					}
				}
				i++;
			}
			Level result;
			if (num2 != -1)
			{
				result = sortLevels[num2];
				offset = num;
			}
			else
			{
				result = StairsBeamCreator.NewLevel(doc, elevation);
				offset = 0.0;
			}
			return result;
		}

		private static Level NewLevel(Autodesk.Revit.DB.Document doc, double elevation)
		{
			return doc.HyNewLevel(elevation);
		}
	}
}
